Challenge: Improving VoiceOver Announcements
On this page
Adding Additional Structure to the MegaNav
Wrapping the MegaNav buttons in h2 headings can help improve screen reader navigation.
Adding aria-haspopup attribute of true to the buttons can indicate there’s content attached to them.
We can repurpose existing content to label our submenu regions by adding an id of megamenu-item1 to the Plan Your Trip button, and similar ids to the other nav buttons. Then each megamenu-submenu can have an aria-labelledby attribute that references its top-level button text, such as “Plan Your Trip”.
// Excerpt from includes/header.html
<nav id="header-megamenu" aria-label="Main">
<div class="megamenu-section">
<h2>
<button aria-expanded="false" aria-haspopup="true" class="megamenu-navitem header-main-item" id="megamenu-item1">
Plan Your Trip
</button>
</h2>
<div class="megamenu-submenu" role="region" aria-labelledby="megamenu-item1">
<div class="megamenu-submenu-group">
<h3 class="megamenu-submenu-header">
Find Your Adventure
</h3>
...Repeating this process for all of the buttons will improve the semantic structure of the menu.
Another improvement we could make is refactoring each of the submenus to use unordered lists instead of divs, since they each contain a list of links. This would add more semantic structure to our MegaNav that would read nicely in a screen reader.
More on these techniques in the Semantic Markup with HTML & ARIA workshop!
Update MegaNav JavaScript
With the nav menu structure updated to use headings, we’ll also have to update the menu.js logic to find the correct parent node. We also can have it toggle the aria-expanded attribute on the nav buttons like it does for the active class. This will add a programmatic indication for submenus when they’re opened or closed, making it more clear to users of Assistive Technologies.
Work and Thought Process Videos
These videos include my thought process and work in implementing the updates to the semantic structure of the MegaNav:
Video Transcript
So from that kind of short view, through just the homepage, we have a number of items we could fix starting with our menu.
So let's go over there. We've got a couple of things that we could fix starting with our menu. So within the header, we'll open this up. We added that H one and we at, by adding an an empty alt attribute to our image within the the logo for the, the header or the link to logo, I should say that made, kept it from saying camp spots, camp spots.
So that was a nice treatment for screen reader usage down in our mega menu. There's a couple things that we could improve. One, it had no semantic structure inside of it. So these headings and they're even called mega menu sub menu header, which kind of triggers the thought that maybe that could be a heading.
So they're under H one, I'd say we could add some semantic structure to our menu, kind of as a, a choice that we could make. This would make the content easier to navigate by headings. So I'm gonna make the choice that these top level items of plan, your trip, ways to stay and resources. I'm gonna wrap those in headings.
So they're coming after the H one, I'm gonna put 'em in H two S so that way they become much more important. So they are inside of H two S and you can wrap buttons. They can be wrapped in headings. That's fine. So that's kind of putting the interactive thing inside of a semantic structure element. We can do that.
That is okay. You can do that with links as well. And then within our mega menu sub menu, these divs that are called mega menu sub menu header. Those could then become H threes. And we've got a number of those who come in here and change. We might need to fiddle with the style a little bit, but that's okay.
So then within our other menus, I'm gonna change these to H threes. So they kind of follow that heading structure. So H threes within our last section for resources, there's adventure ideas about us and contribute. So those all become H threes. So we've also got a bunch of divs. So we've got some candidates to put these in lists, and I think unordered lists are great because they group the number of items.
So that would be a good change that we could make. I'll maybe get started on this.
And we also need to add some interactivity to our buttons for our, these mega menu nav items. So to complete the thought on our mega menu, sub menu groups, I'm gonna put wrap these items in a UL, so that would put inside of mega menu, sub menu group.
And then within inside of those, there are a bunch of divs. So these divs, I can select 'em all with command D check it out, change it to li mega menu sub menu link, which contains an anchor link. And I could go in and change the CSS too. So by making it more semantic some of these CSS classes could go away with a bit of refactoring we'll change just the underlying structure right now.
I think that could be a, a thing that we come back and do a little bit later. Or if I'm writing this from scratch even better than I can just choose more semantic elements from the get go, and then I can write my CSS to utilize those tag names instead of these kind of made up CSS classes.
So in our next mega menu, sub menu group, I'll do the same thing.
So I've got these ULS and inside of them, the divs containing a bunch of links are going to become allies. So this adds groups of links under headings. So definitely more semantic information than we had before. So UL, so I'm gonna just keep on charging through all of these. It's a bit repetitive with this all hard coded.
When we get to using more of a framework driven approach, this stuff will all be built with components and we can kind of target well, much easier. It's not all, not all hard coded with HTML. Okay. I think we're almost there. We're wearing our last section. it's just get her done, get 'em all in there.
So DS all changing to allies and I'm speeding through this so that we can move on to the next thing. So bear with me for a second. So changing all of these divs
last one, and then I'll be done flying through these like this. Okay. So we've got some allies here. So these structured groups, now they have a heading and then a list of links heading list of links. And that makes it really nice. So that there's more structure. It's not just like div soup all the way through these things.
So we might need to change the styles a little bit, but we've seen, we can do that. We've done plenty of that so far today, I believe in us. Okay. So the other thing I'd like to do is indicate that these mega menu nav items have menus attached. And so there's a number of ways that we could do that. I think probably the most straightforward that I would recommend is adding an aria has popup of true.
So these menus are relying on JavaScript to function. So I think it's okay to add some aria attributes to them right from the get go. I think, you know, if we were gonna make this super progressively enhanced, and if you had JavaScript turned off, make everything just visible, then maybe, you know, some of our area, we, yeah, you can kind of play around with different techniques for progressive enhancement for this implementation.
We are going to assume that JavaScript is present. But just sort of a shout out to what's called progressive enhancement. Okay. So one more we'll say aria dash has pop up of true. So that way, when we navigate onto these top level buttons in a screen reader, it will indicate that there's something attached to it.
So pretty awesome. We also we, we wanna go into our JavaScript as well, and we're gonna add something to kind of toggle the state of whether this is open or closed. So
I'm just double checking. What else we wanna add? So there's a, there's quite a few items we could add to make this menu more semantic and read better in the assistive technology. So something that we could also add, so we've got aria has pop up, I'm gonna collapse these sub menu so we can see all three buttons at once.
I could also, oops. Come back over here to vs code. So I'm gonna select all three buttons at once. That was with the command D command, which is our best friend. So I'm gonna say aria dash expanded false. So they're not expanded when the page loads this is kind of what I was talking about with, do we want to apply our state attributes with JavaScript, perhaps we're definitely going to modify these with JavaScript.
When we open a menu, I'm just going to for time purposes right now, we're gonna add this default state. They are not expanded when the page loads they do have sub menus attached to them for aria has pop up. And I think that can work well. So we have got all three of these now kind of have their default state set up.
So in the JavaScript we wanna go and toggle this when this opens we'll change this to true. And when it closes, we'll change it back. So within our JavaScript, this is where, when we could have used the class list dot toggle method we are using add and remove separately that's so that we can come in here and add some Mario kind of on and off.
So our menu item we're on it already to bind this click event. So I could say menu item. So that's this item that we're iterating over and applying a click handler to when it has the active class, we could set an attribute of aria dash expanded. So if it has active, it should be expanded. So it would be true.
And if it is not active, we've removed the active class. We should set that back to false. So kind of toggling it back and forth between true and false for RA expanded.
So let's go see, let's go see what happened. I'm gonna hit save. I'll come back over here to the browser and our camp spots app. We got a little bit of funky styling because we put we wrapped these in each twos and we didn't reset any of the styles, but let's see at least functionally speaking, what's happening with our JavaScript.
So I'm gonna close off this device. Emulator. I'm gonna move our dev tools to be docked back on the bottom. So already expanded. Wait a minute. False. True. I'm hovering over. It is a little bit confusing. So right now it's false. When I've expanded it, it should say true. Oh, you know what happened? We added something.
So there's. Our active class now is getting our parent node is not the right node anymore. So we broke it a little bit. We need to make one more change to our JavaScript. So I'm gonna go back over to our menu JS file right here, where we say menu item dot parent node. We need to go up one more level for the way this is written.
We're kind of stepping up the do tree instead of querying to go find whatever it is. That's the way this is currently written. So if we step up one more parent node, we are getting to the correct element, cuz we added, we kind of injected a, a parent node in there. So let's come back to the browser. I'm gonna hit refresh again.
Our styles are still a little bit jacked up, but that's okay. so if I hit a tab to get onto an item and I expand this, now we are changing our are expanded to be true or false, and that is working better.
Video Transcript
Okay. So we've fixed this functionally, but our styles are not looking so great. so let's go back over to our header and fix this. So header CSS we have got header, let's see, it was mega menu section.
So we could say mega menu section H two. I believe we want margins of zero. I think that will fix some of that. Let's see. Yeah. So that was an improvement. just like our H one up here for our logo. When we injected a heading level in there, it got those default margins. It didn't affect our font style because of the way our CSS is written, but we at least zeroed out those margins.
We need to do something similar for. Down here, these items, mega menu, sub menu header. So that's got some CSS that we could target. We could say, so it was getting the font style before. I think it was just getting whatever, like maybe inherit and zero out the top margins that kind of gets it back to the way it was our lists within here as well.
So within mega menu, sub menu are unordered lists need to have their margins zeroed out or padding. Nope. Nope. It's probably the list items inside mega menu sub menu link. PAing zero. No. Wow. We've got some style in here. So margin left, we need more margins margin. Let's look at this computed box model. So we had some margin already to kind of, set this off to the left.
Oh, so each mega menu, sub menu link. What did we do for those? need to fiddle with the CSS a little bit.
So before I get too off track, I want to go and make some changes. So mega menu, sub menu group, we had the header. I'm gonna go bake those changes in real quick, mega menu, sub menu header. So we need font size inherit and margin top zero.
So that gets these looking better. We also need our mega menu, seven menu links. So zeroing out the margins on the owner ordered list was not doing the trick. We have display flex on these items because they have custom little bullets on here. And so those items they're kind of similar to our link list, further down the page that we also need to go and make changes too.
So I'm gonna cheat and look at what I need to do for these mega menu sub menu UL. So margin zeros in padding, not really doing the thing display flex.. Yeah, that really should be it. Padding zero. Oh, that is it. somehow I missed it. Okay. So that's pretty easy. We can leave these items the way they are, the list items.
It is the UL that we have added in. So mega menu. Sub menu UL let's add a new style mega menu, sub menu, UL margin, zero padding zero. Now we could have a reset style sheet that just zeros out all lists and list items. It could be helpful. I, I do a lot of zeroing out of margins and padding sometimes, but it's also nice when you're writing content to be able to rely on defaults.
And so kind of have to choose which way you wanna go. Do you want defaults to be zeroed out for everything? So then you're having to add margins and padding back in, or do you want to override it in specific cases like this? It's kind of a choice of how you wanna architect your CSS, but now we've got our mega menu working much better,
Video Transcript
There's one more thing I wanna make to the header before we go test it.
in voiceover.
There's one more change that I wanna make we've made this way more structural than it was before. Oh four. I also wanna add a little bit of structure around the rappers around our mega menu items. So on mega menu, sub menu, it's a div right now.
And we've got mega menu sub menu, mega menu, sub menu group. So that's each of the groups kind of within a sub menu. So the mega menu sub menu, that kind of wraps everything for each one of these. I'm gonna give it a roll of region and I'm gonna give it a label. I'm gonna label it by its button so that it's sort of connected to like the button that toggles the menu.
And then the, the element that wraps all of the sub menu items. Give that a bit more programmatic detail by pointing it to it's pointing it to that button. So I'm gonna say aria dash labeled by and are labeled by is kind of a British spelling and has two L's in it. little trivia. So mega menu, I'm pointing it to the idea attribute of the button kind of neighboring it, mega menu item one.
And I did mention earlier I like alphabetizing stuff, so I'm gonna do that. So we've got this. So that's one of 'em on the next one down are ways to stay. We're gonna do something similar of role of region and we'll point this one to aria dash labeled by mega menu dash item two, I'm gonna close, you know, anything you can collapse to make it easier to see sometimes can be helpful.
So we'll do roll of region on the third one and aria dash labeled by mega menu item three. So this adds some kind of semantic grouping to these groups of items. So that they're a little bit more like they reference the buttons in, they, you know, these items neighboring. So between the each twos that we've added that are sort of follow the page hierarchy, we've also added some structure around our sub menu items.
That should be a huge improvement in a screen reader.
Check VoiceOver After Updating the MegaNav
Note: The form fix has already been implemented in a previous lesson
Update a Form to be Semantic (Tools Can’t Catch Everything)
Video Transcript
So let's go over to safari and I'm gonna hit refresh, get everything up to date. So it's looking better. There's a little teeny gap here between the menu buttons and the sub menu. I'm not gonna worry about that right now, but that could be an easy CSS fix.
It might be display and line block, or, you know, some sort of little style treatment, but it doesn't affect the screen reader functionality. So I'm gonna ignore it for the moment to turn voiceover back on. I will do function command F five voiceover on safari camp's window camps. Web content has keyboard focus, visited link camp spots, banner you plan your trip menu, popup button navigation.
So here that menu popup button navigation, and I cut it off before it could say you are currently on a heading level two. So I'll go to the next one ways to stay menu popup button. You are currently on a heading level two. So what that does is indicate to us that there is a popup button here that has something attached to it, and it's a heading level.
So it's kind of an important part of the page. It's got some semantic structure to it. So now if I open this using the return key ways to stay menu popup button, it doesn't really say anything about already expanded, but the popup button is telling us something. So that's really cool. Now our expanded support is kind of mixed.
I think it works a little bit better in N VDA or jaws, but I think we could use it anyway. It's still a really awesome programmatic attribute to add. And so if I arrow down into the content now in the sub menu, it has way more semantic structure stay heading level three trip types. You are link tent, camping.
You are currently on a tax element. You are camping. You are currently on a tax element, van camping. You are currently on a tax element, link, luxury lamping link events, list, two items. So there we get that events list, two items. So that structure that we added with the list that's where it gives us a bit more of that detail.
And so if I come back to the toggle buttons, link, link, link, link ways to stay menu popup, button navigation, ways to stay menu popup button. Yeah. It sure doesn't read out that our expanded does it. But it's still an improvement. Like we know that there's something attached to this mega menu. There's more structure in the menu itself, which is really cool and that I would add.
I'm gonna continue down the page so we can test that modifiers, circumflex thing that we saw, which for some reason, isn't showing up here in the menu.
So I'm glad I didn't really bother with that fix, but it did affect that link list further down the page. So let's go down there. Resources, menu, popup button link login, banner tri Oregon, Colorado edit tech, enter dates, edit text blank, search button link, New York. You are currently on a link to click this all right, link, New York.
We don't get that modifiers circumflex stuff anymore. So that's a huge improvement. I mean it's in terms of user blocking stuff, like we did get some of the major things out of the way, like adding alt text adding button text to things. So we'd already done things for the screen reading experience before we ever got to the step, which is why I love testing with extensions and dev tools.
Cuz you can fix a lot of the low hanging fruit before you get into your screen reader testing pass. Now there's still some things that we could fix. If I scroll up here are input, text fields, for example, are not using label elements quite yet, but they do have placeholders. So it did give us something.
It's not the best experience and I'll tell you why I'll exit out of voiceover voiceover off. When I click on these, what obviously look like labels to me, I click on them. My focus does not go into these text inputs. And also when I start typing, like if I had a date picker that popped up here or I wanna type in, you know, I wanna go to New Zealand, the placeholder text goes away.
And so placeholder alone is not a great thing to rely on. It does so happen that we have text here that could be a label element. So let's fix that real quick. Let's get that satisfaction. Cuz it's a really important thing to, to fix when we're talking about screen reader usage.
Video Transcript
So in our homepage, HTML, we even have a class name of label, which is kind of funny.
So these spans, if I select this and change it to a label element. This text field for the place search has an ID on it. So I can reference that on the label element by typing four place dash search. So that will bind this label with the input element and they need that connection. Either the label element needs to wrap the input, or we need this four ID pairing to make them know about each other.
So date search is similar. We can change this span to a label and wire up this label to match the date dash search. And so I mentioned this kind of here at the end because in terms of user impact for screen readers, form labels is a huge one and it's often forgotten. So if I refresh this, now, if I click on this label text, it's kind of a nice extra, I mean, it's a, a mouse ergonomics thing.
So, you know, it's nice for people who can use the mouse more importantly for these inputs kind of going back to our accessibility inspector, we now have a label of dates and the placeholder gets, it sort of gets replaced. So I think it still does get read out as kind of a description and I'll fire a voiceover back up.
So you can hear what that sounds like, but this is where our dev tools and extensions and things that might have found a missing form label. That's where this all comes together with screen reader usage is that we're testing stuff in dev tools for the purpose of making it work better in a screen reader.
So I often, you know, I'm combining all of these techniques and all of these workflow steps, so that I'm really prepping my webpages so that when I go do screen reader testing, I've already knocked out a lot of these major issues. But in this case, you know, acts didn't complain about these inputs because they had placeholders, which I think placeholder was added as part of this what they calculate for the name, because so many inputs were missing anything otherwise, so better to have a placeholder than nothing at all.
But act won't find that for you. You know, it won't find that you're, you could have found this label text, but didn't so that's another area that the automated tooling might not quite catch things that we could improve. Cuz if placeholder is all there is, and there's no label text at all for cognitive purposes, like it's hard to know once you start typing, what was that field for?
Video Transcript
And so in the screen reader, now let's fire voiceover back up one more time. I'll hit refresh and do function command F five voiceover on safari camp's window camp visited link plan ways to resources linked where to try Oregon, Colorado edit text. Dates enter dates, edit text. You are currently on where to try Oregon, Colorado.
So that really does work better now that it says where to, and then it reads the placeholder. So we get the benefit of the label text and the placeholder text combined, if it was something like a telephone field and the number was phone number or social security number, like those are quite different.
And if the placeholder just had the format, you might be like what is this field for? And so the label text describes what the field is for the placeholder is usually an example of content that can go into it. And that becomes really relevant in our screen reader testing. And so with voiceover, we've found a lot of the underlying accessibility information that could be missing if we only tested with the keyboard we were able to find a lot of stuff with lighthouse and ax.
So we can get a lot of that low hanging fruit before we ever get to screen reader testing. But there's really no substitute, like, as I was mentioning, kind of the final say should go to the screen reader, like, what are the headings doing?
You know, what's actually being read out in the screen readers for the browsers that we support. And so it can be really helpful tool. So yeah, that's a voice over voice over off, we've made some changes.